LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
 
ENTITY TEST_EXEC_UNIT IS
END TEST_EXEC_UNIT;
 
ARCHITECTURE behavior OF TEST_EXEC_UNIT IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT EXECUTE_UNIT
    PORT(
	 
         CLK : IN  std_logic;
         REG_DEST_IN : IN  std_logic;
         ALU_SRC_IN : IN  std_logic;
         ALU_OP_IN : IN  std_logic_vector(5 downto 0);
         BRANCH_IN : IN  std_logic;
         MEM_READ_IN : IN  std_logic;
         MEM_WRITE_IN : IN  std_logic;
         REG_WRITE_IN : IN  std_logic;
         MEM_TO_REG_IN : IN  std_logic;
         CUR_PC_IN : IN  std_logic_vector(31 downto 0);
         IMMEDIATE_IN : IN  std_logic_vector(31 downto 0);
         REGFILE1_IN : IN  std_logic_vector(31 downto 0);
         REGFILE2_IN : IN  std_logic_vector(31 downto 0);
         REGDEST1_IN : IN  std_logic_vector(4 downto 0);
         REGDEST2_IN : IN  std_logic_vector(4 downto 0);
         BRANCH_FLAG_OUT : OUT  std_logic;
         MEM_READ_OUT : OUT  std_logic;
         MEM_WRITE_OUT : OUT  std_logic;
         MEM_TO_REG_OUT : OUT  std_logic;
         REG_WRITE_OUT : OUT  std_logic;
         BRANCH_PC_OUT : OUT  std_logic_vector(31 downto 0);
         BRANCH_OUT : OUT  std_logic;
         ALU_OUT : OUT  std_logic_vector(31 downto 0);
         WRITE_DATA_OUT : OUT  std_logic_vector(31 downto 0);
         REG_DEST_OUT : OUT  std_logic_vector(4 downto 0)
        );
    END COMPONENT;
    

   --Inputs
   signal CLK : std_logic := '0';
   signal REG_DEST_IN : std_logic := '0';
   signal ALU_SRC_IN : std_logic := '0';
   signal ALU_OP_IN : std_logic_vector(5 downto 0) := (others => '0');
   signal BRANCH_IN : std_logic := '0';
   signal MEM_READ_IN : std_logic := '0';
   signal MEM_WRITE_IN : std_logic := '0';
   signal REG_WRITE_IN : std_logic := '0';
   signal MEM_TO_REG_IN : std_logic := '0';
   signal CUR_PC_IN : std_logic_vector(31 downto 0) := (others => '0');
   signal IMMEDIATE_IN : std_logic_vector(31 downto 0) := (others => '0');
   signal REGFILE1_IN : std_logic_vector(31 downto 0) := (others => '0');
   signal REGFILE2_IN : std_logic_vector(31 downto 0) := (others => '0');
   signal REGDEST1_IN : std_logic_vector(4 downto 0) := (others => '0');
   signal REGDEST2_IN : std_logic_vector(4 downto 0) := (others => '0');

 	--Outputs
   signal BRANCH_FLAG_OUT : std_logic;
   signal MEM_READ_OUT : std_logic;
   signal MEM_WRITE_OUT : std_logic;
   signal MEM_TO_REG_OUT : std_logic;
   signal REG_WRITE_OUT : std_logic;
   signal BRANCH_PC_OUT : std_logic_vector(31 downto 0);
   signal BRANCH_OUT : std_logic;
   signal ALU_OUT : std_logic_vector(31 downto 0);
   signal WRITE_DATA_OUT : std_logic_vector(31 downto 0);
   signal REG_DEST_OUT : std_logic_vector(4 downto 0);

   -- Clock period definitions
   constant CLK_period : time := 10 ns;
 
BEGIN
 
	-- Instantiate the Unit Under Test (UUT)
   uut: EXECUTE_UNIT PORT MAP (
          CLK => CLK,
          REG_DEST_IN => REG_DEST_IN,
          ALU_SRC_IN => ALU_SRC_IN,
          ALU_OP_IN => ALU_OP_IN,
          BRANCH_IN => BRANCH_IN,
          MEM_READ_IN => MEM_READ_IN,
          MEM_WRITE_IN => MEM_WRITE_IN,
          REG_WRITE_IN => REG_WRITE_IN,
          MEM_TO_REG_IN => MEM_TO_REG_IN,
          CUR_PC_IN => CUR_PC_IN,
          IMMEDIATE_IN => IMMEDIATE_IN,
          REGFILE1_IN => REGFILE1_IN,
          REGFILE2_IN => REGFILE2_IN,
          REGDEST1_IN => REGDEST1_IN,
          REGDEST2_IN => REGDEST2_IN,
          BRANCH_FLAG_OUT => BRANCH_FLAG_OUT,
          MEM_READ_OUT => MEM_READ_OUT,
          MEM_WRITE_OUT => MEM_WRITE_OUT,
          MEM_TO_REG_OUT => MEM_TO_REG_OUT,
          REG_WRITE_OUT => REG_WRITE_OUT,
          BRANCH_PC_OUT => BRANCH_PC_OUT,
          BRANCH_OUT => BRANCH_OUT,
          ALU_OUT => ALU_OUT,
          WRITE_DATA_OUT => WRITE_DATA_OUT,
          REG_DEST_OUT => REG_DEST_OUT
        );

   -- Clock process definitions
   CLK_process :process
   begin
		CLK <= '0';
		wait for CLK_period/2;
		CLK <= '1';
		wait for CLK_period/2;
   end process;
 

   -- Stimulus process
   stim_proc: process
   begin		
      -- hold reset state for 100 ns.
      wait for 100 ns;	

      wait for CLK_period*10;

		--- <<R TYPE INSTRUCIONS>>
		--- Perform UADD
		ALU_OP_IN <= "001001"; -- ADD instruction
		ALU_SRC_IN <= '0'; -- Source is from register for R type instructions
		BRANCH_IN <= '0'; -- no branch
		REGFILE1_IN <= x"12345678"; -- RS
      REGFILE2_IN <= x"87654321"; -- RT
		REGDEST1_IN <= STD_LOGIC_VECTOR(to_unsigned(10, 5)); -- 
      REGDEST2_IN <= STD_LOGIC_VECTOR(to_unsigned(11, 5)); --
		IMMEDIATE_IN <= x"12341234";
		CUR_PC_IN <= x"14285711";
		REG_DEST_IN <= '1'; -- Select REGDEST2
		
      MEM_READ_IN <= '0'; -- not using memory here
      MEM_WRITE_IN <= '0'; -- not writing to mem
      REG_WRITE_IN <= '1'; -- Saving result to register
      MEM_TO_REG_IN <= '0'; -- not reading from mem
		
		wait for CLK_PERIOD;
		
		--- <<I TYPE INSTRUCTIONS>>
		--- Perform LW
		ALU_OP_IN <= "001001"; -- ADD instruction required for determining address
		ALU_SRC_IN <= '1'; -- Source is from immediate
		BRANCH_IN <= '0'; -- no branch
		REGFILE1_IN <= x"12345678"; -- RS
      REGFILE2_IN <= x"87654320"; -- RT, SHOULD NOT MATTER, not used
		REGDEST1_IN <= STD_LOGIC_VECTOR(to_unsigned(10, 5)); -- destination should be RT
      REGDEST2_IN <= STD_LOGIC_VECTOR(to_unsigned(11, 5)); --
		IMMEDIATE_IN <= x"12341234";
		CUR_PC_IN <= x"14285711";
		REG_DEST_IN <= '0'; -- Select REGDEST1
		
      MEM_READ_IN <= '1'; -- Doing a memory read
      MEM_WRITE_IN <= '0'; -- not writing to mem
      REG_WRITE_IN <= '1'; -- Saving result from register
      MEM_TO_REG_IN <= '1'; -- reading from RAM

		--- Perform SW
		ALU_OP_IN <= "001001"; -- ADD instruction required for determining address
		ALU_SRC_IN <= '1'; -- Source is from immediate
		BRANCH_IN <= '0'; -- no branch
		REGFILE1_IN <= x"00000000"; -- RS, base of 0
      REGFILE2_IN <= x"87654320"; -- RT, the value to be written
		REGDEST1_IN <= STD_LOGIC_VECTOR(to_unsigned(10, 5)); -- should not matter
      REGDEST2_IN <= STD_LOGIC_VECTOR(to_unsigned(11, 5)); -- should not matter
		IMMEDIATE_IN <= x"00000000"; -- offset of 0
		CUR_PC_IN <= x"14285711"; -- should not matter
		REG_DEST_IN <= '0'; -- Select REGDEST1
		
      MEM_READ_IN <= '0'; -- not reading to mem
      MEM_WRITE_IN <= '1'; -- writing to mem
      REG_WRITE_IN <= '0'; -- not writing to mem
      MEM_TO_REG_IN <= '0'; -- not reading from mem     
		
		wait for CLK_PERIOD;
		
		
      wait;
   end process;

END;
